#ifndef QPROPERTY_H
#define QPROPERTY_H

#include "QtPropertyExplorerLib.h"

#include <QVariant>
#include <QString>
#include <QSharedPointer>
#include <QStyleOptionViewItem>
#include <QAbstractItemDelegate>

namespace QPE {

class QPropertyPrivate;

class QTPROPERTYEXPLORER_DLL_EXPORT QProperty
{
public:
	enum DPC_DisplayColumn {
		DPC_Name = 0,
		DPC_Data
	};

	//! Standard constructor, takes a name and a parent property as argument
	explicit QProperty(const QString& name, QVariant::Type type = QVariant::String);

	//! Destructor
	virtual ~QProperty();

	//! Returns a string containing the type of the property
	virtual QString type() const;

	//! Get the data how it should be displayed
	virtual QVariant data (int column = DPC_Name, int role = Qt::DisplayRole) const;

	//! This is used by the model to set the data
	//! \param data The data to set
	//! \param role The role. Default is Qt::EditRole
	//! \return Returns true, if the data was changed, false if not.
	virtual bool setData (const QVariant& data, int role = Qt::EditRole);

	//! This is called by the delegate when the property value is being drawn.
	//! The standard implementation doesn't do anything.
	//! If you reimplement this in a sub property, make sure to return true or the delegate will draw the item.
	virtual bool paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QAbstractItemDelegate* delegate) const;

	//! Returns an editor widget, or NULL if it doesn't supply one
	//! \param parent The widget to which the editor will be added as a child
	//! \options Render options
	//! \delegate A pointer to the QAbstractItemDelegate requesting the editor. This can be used to connect signals and slots.
	virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& options, const QAbstractItemDelegate* delegate);

	//! Sets the property's data to the editor (returns false, if the standard delegate should do that)
	virtual bool setEditorData(QWidget* editor);

	//! Gets the data from the widget
	virtual QVariant getEditorData(QWidget* editor) const;

	//! Returns item flags
	virtual Qt::ItemFlags flags(int column = DPC_Name) const;

	//! Sets the value of the property
	virtual void setValue(const QVariant& value);

	//! Returns the value of the property as a QVariant
	virtual QVariant getValue() const;

	//! Serializes the value to a string
	virtual QString serialize() const;

	//! Deserializes the value from a string
	virtual void deserialize(const QString& value);

	// The following functions are experimental and not yet implemented.
	/*//! Returns a pointer to the data stored and handled by this property. In most cases this function shouldn't be used.
	//! \return Returns a void pointer to the data. Not all properties have to support this. By default, this implementation returns a NULL pointer.
	virtual void* getDataPointer();

	//! Sets the data.
	//! \return Returns a void pointer to the data. Not all properties have to support this. By default, this implementation returns a NULL pointer.
	virtual bool setDataPointer(void* pointer);*/

	//! Sets the name of the property
	virtual void setName(const QString& name);

	//! Gets the name of the property
	virtual QString getName() const;

	//! Sets the name of the property
	virtual void setDescription(const QString& desc);

	//! Gets the name of the property
	virtual QString getDescription() const;

	//! Adds a child to this property
	virtual int addChild(QProperty* child);

	//! Returns a reference to the list of children
	virtual QList<QProperty*>& getChildren();

	//! Returns a reference to the list of children
	virtual const QList<QProperty*>& getChildren() const;

	//! Returns the child at a certain row
	virtual QProperty* getChild(int row) const;

	//! Gets the number of children
	virtual int getRowCount() const;

	//! Gets the parent of this property
	virtual QProperty* getParent() const;

	//! Sets the parent of this property
	virtual void setParent(QProperty* parent);

	//! Removes a child from the children list, doesn't delete the child!
	virtual void removeChild(QProperty* child);

	//! Returns the row the child has
	virtual int getChildRow(QProperty* child) const;

	//! Returns whether the views have to update the parent of this property if it changes
	virtual bool getUpdateParent() const;

	//! Returns whether the views have to update the children of this property if it changes
	virtual bool getUpdateChildren() const;

	//! Sets whether the views should update Parents or children after this property changes
	virtual void setUpdateBehaviour(bool update_parent, bool update_children);

	//! Sets the settings by calling the overloaded setSetting(const QString& key, const QVariant& value) for each item in the map.
	virtual void setSettings(const QMap<QString, QVariant>& settings);

	//! Get the settings.
	virtual QMap<QString, QVariant> getSettings() const;

	//! Sets the settings. This function has to be implemented in a subclass in order to have an effect
	virtual void setSetting(const QString& key, const QVariant& value);

	//! Get the settings. This function has to be implemented in a subclass in order to have an effect
	virtual QVariant getSetting(const QString& key) const;

	//! Returns the list of keys of the property's settings
	virtual QStringList getSettingKeys() const;

	//! Clones this property
	//! \param include_children Indicates whether to also clone the children
	//! \param container If a property is being passed here, no new QProperty is being created but instead it is tried to fill all the data into container. This can also be used when subclassing this function.
	//! \return Returns the newly created property (or container, if it was not NULL)
	virtual QProperty* clone(bool include_children = true, QProperty* container = NULL) const;


protected:
	//! Protected constructor
	QProperty(QPropertyPrivate* d);

	//! The protected structure holding the member variables (to assure binary compatibility)
	QPropertyPrivate* d_ptr;

private:
	// Provide access functions for the d_ptr
	Q_DECLARE_PRIVATE(QProperty)
};

}

#endif // QPROPERTY_H
